#ifndef TEMPLE_UTIL_STRING_H_
#define TEMPLE_UTIL_STRING_H_

#include "util/stdc.h"
#include "openssl/md5.h"
#include "openssl/sha.h"
#include <vector>
namespace util {

inline string ltrim(const string &raw)
{
    int i;
    int len = raw.length();

    for (i=0; i<len; ++i)
    {
        if (!isspace(raw[i]))
            break;
    }

    return raw.substr(i, len-i);
}

inline string ltrim(string &&raw)
{
    int i;
    int len = raw.length();

    for (i=0; i<len; ++i)
    {
        if (!isspace(raw[i]))
            break;
    }

    return raw.substr(i, len-i);
}

inline string rtrim(const string &raw)
{
    int i;
    int len = raw.length();

    for (i=len-1; i>=0; i--)
    {
        if (!isspace(raw[i]))
            break;
    }

    return raw.substr(0, i+1);
}

inline string rtrim(string &&raw)
{
    int i;
    int len = raw.length();

    for (i=len-1; i>=0; i--)
    {
        if (!isspace(raw[i]))
            break;
    }

    return raw.substr(0, i+1);
}

inline string trim(const string &raw)
{
    int i, j;
    int len = raw.length();

    for (i=0; i<len; ++i)
    {
        if (!isspace(raw[i]))
            break;
    }

    for (j=len-1; j>=i; --j)
    {
        if (!isspace(raw[j]))
            break;
    }

    return raw.substr(i, j-i+1);
}

inline string trim(string &&raw)
{
    int i, j;
    int len = raw.length();

    for (i=0; i<len; ++i)
    {
        if (!isspace(raw[i]))
            break;
    }

    for (j=len-1; j>=i; --j)
    {
        if (!isspace(raw[j]))
            break;
    }

    return raw.substr(i, j-i+1);
}

inline std::vector<string> split(const string &raw, char sep)
{
    string::size_type pos1 = 0;
    string::size_type pos2 = 0;
	string::size_type len = raw.length();
	std::vector<string> vec;

	while (true)
    {
        if (pos1 >= len)
        {
            vec.push_back("");
            break;
        }

        pos2 = raw.find_first_of(sep, pos1);
        if (pos2 == string::npos)
        {
            vec.push_back(trim(raw.substr(pos1, string::npos)));
            break;
        }
        else
        {
            vec.push_back(trim(raw.substr(pos1, pos2-pos1)));
            pos1 = pos2+1;
        }
    }

    return std::move(vec);
}

inline std::vector<string> split(string &&raw, char sep)
{
    string::size_type pos1 = 0;
    string::size_type pos2 = 0;
	string::size_type len = raw.length();
	std::vector<string> vec;

	while (true)
    {
        if (pos1 >= len)
        {
            vec.push_back("");
            break;
        }

        pos2 = raw.find_first_of(sep, pos1);
        if (pos2 == string::npos)
        {
            vec.push_back(trim(raw.substr(pos1, string::npos)));
            break;
        }
        else
        {
            vec.push_back(trim(raw.substr(pos1, pos2-pos1)));
            pos1 = pos2+1;
        }
    }

    return std::move(vec);
}

inline string to_string(bool val)
{
    if (val)
        return "true";
    else
        return "false";
}

inline string to_md5(const string &in)
{
    unsigned char md[16];
    char out[64];

    MD5((const unsigned char *)in.c_str(), in.length(), md);

    snprintf(out, sizeof(out), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
        md[0],md[1],md[2],md[3],md[4],md[5],md[6],md[7],md[8],md[9],md[10],md[11],md[12],md[13],md[14],md[15]);

    return out;
}

inline string to_sha1(const string &in)
{
    unsigned char md[20];
    char out[64];

    SHA1((const unsigned char *)in.c_str(), in.length(), md);

    snprintf(out, sizeof(out), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
        md[0],md[1],md[2],md[3],md[4],md[5],md[6],md[7],md[8],md[9],md[10],md[11],md[12],md[13],md[14],md[15],md[16],md[17],md[18],md[19]);

    return out;
}

}
#endif //TEMPLE_UTIL_STRING_H_
